
package fileby.model.impl.filemanagement.impl;

import fileby.model.impl.filemanagement.IFileHandler;
import java.awt.Desktop;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import javax.swing.TransferHandler;

/**
 *
 * @author Oscar
 */
public class FileHandler implements IFileHandler {

    private boolean copy = true;

    public boolean delete(List<File> fileList) throws SecurityException {
        boolean allFilesDeleted = false;
        if (fileList == null) {
            return false;
        }
        for (File file : fileList) {
            if (file.isDirectory()) {
                delete(Arrays.asList(file.listFiles()));
            }
            allFilesDeleted = file.delete();
        }
        return allFilesDeleted;
    }

    public boolean rename(File file, File newName) throws SecurityException {
        if (file != null && newName != null) {
            return file.renameTo(newName);
        }
        return false;
    }

    public void run(List<File> fileList) throws IllegalArgumentException, IOException, SecurityException {
        if (Desktop.isDesktopSupported() && fileList != null) {
            for (File file : fileList) {
                if (file != null) {
                    Desktop.getDesktop().open(file);
                }
            }
        }
    }

    public void copy(List<File> fileList) throws IllegalStateException {
        ClipboardManager.getInstance().setClipboardContent(fileList);
        copy = true;
    }

    public void cut(List<File> fileList) throws IllegalStateException {
        ClipboardManager.getInstance().setClipboardContent(fileList);
        copy = false;
    }

    public boolean lastActionWasCopy() {
        return copy;
    }

    public List<File> getClipboardContent() throws IllegalStateException, UnsupportedFlavorException, IOException {
        return ClipboardManager.getInstance().getClipboardContent();
    }

    public void createFolder(String dir) throws SecurityException {
        boolean created = false;
        boolean conflict = false;
        File newFolder = new File(dir + "\\New Folder");
        File directory = new File(dir);
        created = newFolder.mkdir();
        int i = 1;

        while (!created) {
            newFolder = new File(dir + "\\New Folder (" + i + ")");
            created = newFolder.mkdir();
            i++;
            if (!created) {
                for (String name : directory.list()) {
                    if (newFolder.getName().equals(name)) {
                        conflict = true;
                        break;
                    }
                }
                if (!conflict) {
                    throw new SecurityException("You dont have the permission to create a new folder in this directory.");
                }
            }
        }
    }

    public boolean addFiles(List<File> fileList, File location, int action) throws IOException {
        if (fileList == null || location == null) {
            return false;
        }

        String filePath = location.getAbsolutePath();
        boolean allowAction = true;
        boolean conflict = false;

        for (File f : fileList) {
            if (f.getParent() == null || f.getParent().equals(filePath) || f.getAbsolutePath().equals(filePath)) {
                allowAction = false;
                break;
            }
            if (location.isDirectory()) {
                for (String name : location.list()) {
                    if (f.getName().equals(name)) {
                        conflict = true;
                    }
                }
            } else {
                throw new IOException("You are not allowed to move files to this folder");
            }
        }

        if (action == TransferHandler.MOVE) {
            if (allowAction && !conflict) {
                for (File file : fileList) {
                    if (!file.renameTo(new File(location.getAbsoluteFile(), file.getName()))) {
                        throw new IOException("All files could not be moved");
                    }
                }
                return true;
            }
        } else if (action == TransferHandler.COPY) {
            if (allowAction && !conflict) {
                for (File file : fileList) {
                    if (file.isFile()) {
                        if (!copyFile(file, filePath + '/' + file.getName())) {
                            throw new IOException(file.getName() + " could not be copied");
                        }
                    } else if (file.isDirectory()) {
                        File dir = new File(filePath + '/' + file.getName());
                        if (dir.mkdir()) {
                            if (file.listFiles().length > 0) {
                                addFiles(Arrays.asList(file.listFiles()), dir, action);
                            }
                        } else {
                            throw new IOException(file.getName() + " could not be copied");
                        }
                    }
                }
                return true;
            }
        }
        if (allowAction && conflict) {
            throw new IOException("Conflict, files with the same name.");
        }
        return false;
    }

    private boolean copyFile(File file, String pathToCopy) throws IOException {
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(file);
            out = new FileOutputStream(new File(pathToCopy));
            byte[] bytes = new byte[1024];
            while (in.read(bytes) > -1) {
                out.write(bytes);
            }
            return true;
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {}
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {}
        }
    }

}
